import type { WebSocketOptions, WebSocketState } from './index';

/**
 * websocket client 类
 * @author lianqq
 */
export class WebSocketClient {
  private static instance: WebSocketClient; // 实例
  private options: WebSocketOptions; // 配置项
  private state: WebSocketState; // 状态

  private constructor(options: WebSocketOptions) {
    // 默认配置
    this.options = {
      heartbeatInterval: 30000, // 30s
      reconnectInterval: 5000,  // 5s
      reconnectAttempts: 5,
      heartbeatMessage: 'ping',
      ...options
    };

    this.state = {
      connected: false,
      reconnectCount: 0
    };

    this.connect();
  }

  /**获取单例 */
  public static getInstance(options: WebSocketOptions): WebSocketClient {
    if (!WebSocketClient.instance) {
      WebSocketClient.instance = new WebSocketClient(options);
    }
    return WebSocketClient.instance;
  }

  /**连接 */
  private connect(): void {
    try {
      this.state.ws = new WebSocket(this.options.url);
      this.attachEventListeners();
    } catch (error) {
      console.error('WebSocket connection error:', error);
      this.reconnect();
    }
  }

  /**添加监听 */
  private attachEventListeners(): void {
    if (!this.state.ws) return;

    this.state.ws.onopen = (event: Event) => {
      this.state.connected = true;
      this.state.reconnectCount = 0;
      // this.startHeartbeat();
      this.options.onOpen?.(event);
    };

    this.state.ws.onmessage = (event: MessageEvent) => {
      if (event.data === 'pong') {
        return;
      }
      this.options.onMessage?.(event);
    };

    this.state.ws.onerror = (event: Event) => {
      this.options.onError?.(event);
    };

    this.state.ws.onclose = (event: CloseEvent) => {
      this.state.connected = false;
      this.stopHeartbeat();
      this.options.onClose?.(event);
      this.reconnect();
    };
  }

  /**开始监听心跳 */
  private startHeartbeat(): void {
    this.stopHeartbeat();
    this.state.heartbeatTimer = window.setInterval(() => {
      this.sendHeartbeat();
    }, this.options.heartbeatInterval);
  }

  /**停止监听心跳 */
  private stopHeartbeat(): void {
    if (this.state.heartbeatTimer) {
      clearInterval(this.state.heartbeatTimer);
      this.state.heartbeatTimer = undefined;
    }
  }

  private sendHeartbeat(): void {
    this.send(this.options.heartbeatMessage as string);
  }

  /**重连 */
  private reconnect(): void {
    if (
      this.state.reconnectCount >= (this.options.reconnectAttempts as number) ||
      this.state.reconnectTimer
    ) {
      return;
    }

    this.state.reconnectTimer = window.setTimeout(() => {
      this.state.reconnectCount++;
      this.state.reconnectTimer = undefined;
      this.connect();
    }, this.options.reconnectInterval);
  }

  /**发送消息 */
  public send(message: string | ArrayBufferLike | Blob | ArrayBufferView): void {

    console.log("message:", message);


    if (this.state.connected && this.state.ws) {
      this.state.ws.send(message);
    } else {
      console.warn('WebSocket is not connected');
    }
  }

  /**关闭 */
  public close(): void {
    this.stopHeartbeat();
    if (this.state.reconnectTimer) {
      clearTimeout(this.state.reconnectTimer);
    }
    this.state.ws?.close();
  }

  public getState(): WebSocketState {
    return { ...this.state };
  }
}